﻿using System;
using System.Collections;
using System.Xml;
using System.Text;
using InfoJetSoft.Service.Entity;
using InfoJetSoft.Service.Util;

namespace InfoJetSoft.Service.Worker
{

	class FormBuildFieldListByXMLDocWorker
	{
		//根据Form.XmlDoc构造FieldList,将每个XmlNode转换成一个Field.
		//同时未每个XmlElement生成一个JetId,作为属性添加到XmlElement上.
		//如果onlyJetId是true,不刷新Form.FieldList.
		public static void buildFieldListByXMLDoc(Form form,bool onlyJetId)
		{
			XmlElement root = form.XmlDoc.DocumentElement;
			ArrayList idList = new ArrayList();
			idList.Add(0);
			if( onlyJetId )
			{
				buildFieldByElement(form.Manifest, new ArrayList(), root, idList);
			}
			else
			{
                //CID 0925 //2011.05.30 //Begin
                form.FieldList.Clear();
                //CID 0925 //2011.05.30 //End
				buildFieldByElement(form.Manifest, form.FieldList, root, idList);
			}
			buildPiList(form);
		}
		
		private static void buildFieldByElement( Manifest manifest, ArrayList fieldList, XmlElement element, ArrayList idList)
		{
			string id = buildElementJetID(element, idList);

			bool hasOneTextChild = DOMUtil.hasOneTextChild(element);
			//CID 0331 //2009.07.27 //Begin
			if( SchemaTypeWorker.isXhtmlElementByLocalName( manifest, element.LocalName ) )
			{
				hasOneTextChild = true;
				DOMUtil.removeInnerJetId( element );
                //CID 1022 //2011.10.17 //Begin
                string fieldValue = null;
                if (manifest.FormFieldsCacheEnabled)
                {
                    //CID 1022 //2011.11.07 //Begin
                    if (ConfigUtil.EnableRichText())
                    {
                        fieldValue = element.InnerXml.Replace("&", "&amp;");
                    }
                    else
                    {
                        fieldValue = element.InnerXml;
                    }
                    //CID 1022 //2011.11.07 //End
                }
                else
                {
                    fieldValue = element.InnerXml.Replace("&", "&amp;");
                }
                //CID 1022 //2011.10.17 //End
				Field elementField = new Field(id, fieldValue);
				elementField.IsRichText = true;
				fieldList.Add( elementField );
			}
			else
			{
				string value_Renamed = null;
				if (hasOneTextChild)
				{
					value_Renamed = element.InnerText;
				}
				else
				{
					value_Renamed = "";
				}
			
				Field elementField = new Field(id, value_Renamed);
				fieldList.Add( elementField );
			}
			//CID 0331 //2009.07.27 //End

			XmlAttribute idAttr = (XmlAttribute) element.GetAttributeNode(JetConstant.JetId);
			if (idAttr != null)
			{
				element.RemoveAttributeNode(idAttr);
			}
			foreach (XmlAttribute attr in element.Attributes)
			{
				string attrId = id + "@" + attr.Name;
				Field attrField = new Field(attrId, attr.Value);
				fieldList.Add( attrField );
			}

			element.SetAttribute(JetConstant.JetId, id);
			fieldList.Add( new Field(id + "@" + JetConstant.JetId, id) );
			
			if (hasOneTextChild)
			{
				return;
			}

			XmlNodeList nodeList = element.ChildNodes;
			for(int i = 0; i < nodeList.Count; i ++)
			{
				XmlNode node = (XmlNode) nodeList[ i ];
				if (node is XmlElement)
				{
					XmlElement subElement = (XmlElement) node;
					ArrayList newIDList = cloneList(idList);
					newIDList.Add(i);
					buildFieldByElement(manifest, fieldList, subElement, newIDList);
				}
				else if (node is XmlText)
				{
					XmlText subText = (XmlText) node;
					ArrayList newIDList = cloneList(idList);
					newIDList.Add(i);
					buildFieldByText(fieldList, subText, newIDList);
				}
			}
		}
		
		private static void buildFieldByText(ArrayList fieldList, XmlText text, ArrayList idList)
		{
			string textID = buildTextJetID(idList);
			string value_Renamed = text.Value;
			fieldList.Add(new Field(textID, value_Renamed));
		}
		
		private static string buildTextJetID(ArrayList idList)
		{
			StringBuilder id = new StringBuilder();
			id.Append("_");
			for (int i = 0; i < idList.Count; i++)
			{
				System.Int32 intID = (System.Int32) idList[ i ];
				id.Append(intID.ToString());
				id.Append("_");
			}
			id.Append(":");
			return id.ToString();
		}
		
		private static string buildElementJetID(XmlElement element, ArrayList idList)
		{
			StringBuilder id = new StringBuilder();
			id.Append("_");
			for (int i = 0; i < idList.Count; i++)
			{
				System.Int32 intID = (System.Int32) idList[ i ];
				id.Append(intID.ToString());
				id.Append("_");
			}
			id.Append(element.Name);
			return id.ToString();
		}
		
		private static ArrayList cloneList(ArrayList idList)
		{
			ArrayList newIDList = new ArrayList();
			for (int i = 0; i < idList.Count; i++)
			{
				newIDList.Add(idList[ i ]);
			}
			return newIDList;
		}

		private static void buildPiList(Form form)
		{
			ArrayList piFieldList = new ArrayList();
			XmlDocument doc = form.XmlDoc;
			XmlNodeList nodeList = doc.ChildNodes;
			foreach (XmlNode node in nodeList)
			{
				if (node is XmlProcessingInstruction)
				{
					XmlProcessingInstruction pi = (XmlProcessingInstruction) node;
					piFieldList.Add(new Field(pi.Name, pi.Value));
				}
			}
			form.PiFieldList = piFieldList;
		}
	}
}